/*
 * @Description: 新增检测计划弹窗上下文
 * @Author: Rfan
 * @Date: 2022-10-12 11:39:09
 * @LastEditTime: 2022-10-22 17:30:32
 */

import { createContext, useContext, useReducer } from 'react';
import { AddPlanDialogReducer } from '../reducers/AddPlanDialogReducer';
import { editItemById, insertItem, selectItemByKey } from '@/utils/list';
import {
  SET_CURRENT_PLAN_INFO,
  SET_CURRENT_STEP,
  SET_DIALOG_TYPE,
  SET_DIALOG_VISIBLE,
  SET_LEVEL_FIELD_LIST,
  SET_OBJ_TYPE,
  SET_RULE_OBJ
} from '../../../../constants';
import {
  CheckedObjType,
  CheckProps,
  fieldCheckType,
  metadataTypeList,
  paneList
} from '../../../../dictionaries';
import {
  addDetectionRule,
  editDetectionRule,
  fetchDetectionRule
} from '@/api/standardizedDetection/detectionPlan';
import { cloneDeep } from 'lodash-es';

class RuleItem {
  ruleType;

  ruleValid;

  constructor(type, valid = false) {
    this.ruleType = type;
    this.ruleValid = valid;
  }
}

class FieldRuleItem {
  field;
  key;
  rules;

  constructor(field = '', idx, rules) {
    this.field = field;
    this.key = `${field}${idx}`;
    this.rules = rules;
  }
}

export const EnumDialogType = { add: 'add', edit: 'edit' };

const initialState = {
  // 弹窗展示状态
  visible: false,
  // 弹窗打开方式：新增 或 编辑 'add' | 'edit'
  dialogType: EnumDialogType.add,
  // 当前的检测类型
  currentObjType: {},
  // 当步骤条位置
  currentStep: 0,
  initRule: {},
  // 被检测字段列表
  levelFieldList: [],
  // 检测方案对象
  currentPlanInfo: {},
  // 检测规则对象
  currentRuleInfo: {},

  // -------- 字典 --------
  // 四性检测列表
  paneList,
  fieldCheckType,
  metadataTypeList
};

const AddPlanDialogContext = createContext();

const AddPlanDialogContextProvider = (props) => {
  const [state, dispatch] = useReducer(AddPlanDialogReducer, initialState);

  const actions = {
    /**
     * @description: 设置弹窗展示状态
     */
    setDialogVisible(visible) {
      dispatch({ type: SET_DIALOG_VISIBLE, visible });
    },

    /**
     * @description: 设置弹窗类型
     */
    setDialogType(data) {
      dispatch({ type: SET_DIALOG_TYPE, data });
    },
    /**
     * @description: 设置步骤条进度
     */
    setCurrentStep(data) {
      dispatch({ type: SET_CURRENT_STEP, data });
    },

    /**
     * @description: 打开新增全宗弹窗
     */
    setObjType(data) {
      dispatch({ type: SET_OBJ_TYPE, data });
    },

    /**
     * @description: 设置被检测字段
     */
    setLevelFieldList(data) {
      dispatch({ type: SET_LEVEL_FIELD_LIST, data });
    },

    /**
     * @description: 设置当前选中的方案数据
     */
    setCurrentPlanInfo(data) {
      dispatch({ type: SET_CURRENT_PLAN_INFO, data });
    },

    /**
     * @description: 获取当前选中的规则数据
     */
    getDetectionRules(query) {
      return new Promise((resolve, reject) => {
        fetchDetectionRule(query)
          .then((res) => {
            const { data } = res;
            dispatch({ type: SET_RULE_OBJ, data: data?.[0] || {} });
            resolve(data);
          })
          .catch((err) => reject(err));
      });
    },

    /**
     * @description: 设置当前选中的规则数据
     */
    setDetectionRules(data) {
      dispatch({ type: SET_RULE_OBJ, data });
    },

    /**
     * @description: 合并选择的字段与之前保存的字段
     * @param {number} type 检测属性类型
     * @param {number} level 当前选中层级
     * @param {any} initRules 没有已有规则时的默认规则
     * @param {number} authFormType 条目真实性规则用的表单类型，1-字段，2-编制
     * @return {any} 当前层级规则
     */
    combineLeveAndRulesInfo(type, level, initRules, authFormType = 1) {
      const propRules = actions.getPropertyRules(type)?.rules || [];
      // 真实性多一个层级
      const levelRulesList = selectItemByKey(authFormType, propRules, 'ruleType')?.rules || [];
      // 真实性使用levelRulesList，完整性直接使用propRules即可
      const currentLevelRule = selectItemByKey(
        level,
        type === CheckProps.Authenticity ? levelRulesList : propRules,
        'level'
      );
      const currentLevelField = selectItemByKey(level, state.levelFieldList, 'level') || [];
      console.log('context', level, propRules);
      return currentLevelField.fieldList.map((item, idx) => {
        if (currentLevelRule) {
          const fieldRule = selectItemByKey(item, currentLevelRule.rules, 'field');
          return fieldRule || new FieldRuleItem(item, idx, cloneDeep(initRules));
        } else {
          return new FieldRuleItem(item, idx, cloneDeep(initRules));
        }
      });
    },

    /**
     * @description: 全选规则
     * @param {*} propTypeList 规则列表
     * @return {*} 包含新状态的规则列表
     */
    selectAllRules(propTypeList) {
      return propTypeList.map((item) => new RuleItem(item, true));
    },

    /**
     * @description: 反选规则
     * @param {*} propTypeList 规则列表
     * @param {*} selectItem 当前选中的规则
     * @return {*} 包含新状态的规则列表
     */
    selectInverseRules(propTypeList, selectItem) {
      const selectIds = selectItem.filter((item) => item.ruleValid).map((item) => item.ruleType);
      const inverseIds = propTypeList.filter((id) => selectIds.indexOf(id) < 0);
      return inverseIds.map((item) => new RuleItem(item, true));
    },

    /**
     * @description: 获取规则选中状态
     * @param {*} type 检测类型
     * @param {any[]} ruleList 规则列表
     * @return {boolean} 选中状态
     */
    getRuleState(type, ruleList) {
      const currentRule = selectItemByKey(type, ruleList, 'ruleType');
      return currentRule?.ruleValid;
    },

    /**
     * @description: 设置规则选中状态
     * @param {boolean} valid 选中状态
     * @param {any} type 真实性检测类型
     * @param {any[]} ruleList 规则列表
     * @param {*} setRuleList 设置规则列表
     */
    setRuleState(valid, type, ruleList, setRuleList) {
      const currentRule = selectItemByKey(type, ruleList, 'ruleType');
      const editRule = currentRule
        ? editItemById(type, { ...currentRule, ruleValid: valid }, ruleList, 'ruleType')
        : insertItem({ ruleType: type, ruleValid: valid }, ruleList);
      setRuleList(editRule);
    },

    /**
     * @description: 获取某一四性检测规则
     * @param {CheckProps} type
     * @return {any} 查找到的规则
     */
    getPropertyRules(type) {
      const ruleJson = state.currentRuleInfo.detectionRuleJson;
      const ruleList = ruleJson ? JSON.parse(ruleJson) : [];
      return selectItemByKey(type, ruleList, 'ruleType') || {};
    },

    /**
     * @description: 保存检测规则
     * @param {*} params
     */
    saveRulesFunc(params) {
      return new Promise((resolve) => {
        if (state.currentRuleInfo.id) {
          params.id = state.currentRuleInfo.id;
          editDetectionRule(params).then((res) => {
            console.log(res.data);
            const { data } = res;
            // dispatch({ type: SET_RULE_OBJ, data });
            resolve(data);
          });
        } else {
          addDetectionRule(params).then((res) => {
            console.log(res.data);
            const { data } = res;
            // dispatch({ type: SET_RULE_OBJ, data });
            resolve(data);
          });
        }
      });
    }
  };

  const filter = {
    showPaneListByType: (type) => {
      const paneList = state.paneList;
      switch (type) {
        case CheckedObjType.Entry: {
          return paneList.filter((pane) => pane.id !== 3);
        }

        case CheckedObjType.Original: {
          return paneList.filter((pane) => pane.id !== 2);
        }

        case CheckedObjType.EEP: {
          return paneList.filter((pane) => [1, 4].indexOf(pane.id) !== -1);
        }

        case CheckedObjType.Environment: {
          return paneList.filter((pane) => pane.id === 3);
        }

        default: {
          return paneList;
        }
      }
    }
  };

  return (
    <AddPlanDialogContext.Provider value={{ ...state, ...actions, ...filter }}>
      {props.children}
    </AddPlanDialogContext.Provider>
  );
};

export const useAddPlanDialogContext = () => {
  return useContext(AddPlanDialogContext);
};

export { AddPlanDialogContext, AddPlanDialogContextProvider };
